package pl.edu.agh.uddiProxy.client;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.ChangeListener;
import com.google.gwt.user.client.ui.ClickListener;
import com.google.gwt.user.client.ui.Grid;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.Hyperlink;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.ListBox;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;

public class ParametersSearchPanel extends VerticalPanel {
	protected static final int LIMIT = 10;
	private VerticalPanel constructDynamicQueryPanel;
	private VerticalPanel constructStaticQueryPanel;
	private Map<String, Parameter> map;
	
	private Map<ListBox, QueryHorizontalPanel> widgetMap = new HashMap<ListBox, QueryHorizontalPanel>();
	private Button searchButton = new Button("search");
	private Grid grid = new Grid();
	private TModelPanel modelPanel;
	private ClickListener searchListener;
	
	public ParametersSearchPanel() {
		constructDynamicQueryPanel = new VerticalPanel();
		constructDynamicQueryPanel.setHorizontalAlignment(VerticalPanel.ALIGN_CENTER);
		constructDynamicQueryPanel.setWidth("100%");
		
		constructStaticQueryPanel = new VerticalPanel();
		constructStaticQueryPanel.setHorizontalAlignment(VerticalPanel.ALIGN_CENTER);
		constructStaticQueryPanel.setWidth("100%");

		setHorizontalAlignment(VerticalPanel.ALIGN_CENTER);
		setWidth("100%");
		
		grid.setCellSpacing(20);
		
		Label dynamicLabel = new Label("Dynamic parameters:");
		Label staticLabel = new Label("Static parameters:");
		
		add(dynamicLabel);
		add(constructDynamicQueryPanel);
		add(new HTML("<hr>"));
		add(staticLabel);
		add(constructStaticQueryPanel);
		add(new HTML("<hr>"));
		add(searchButton);
		add(grid);
		
		setCellHorizontalAlignment(dynamicLabel, VerticalPanel.ALIGN_LEFT);
		setCellHorizontalAlignment(staticLabel, VerticalPanel.ALIGN_LEFT);
		
		final SearchServiceAsync searchServiceAsync = SearchService.Util.getInstance();
		searchListener = new ClickListener() {
			
			public void onClick(Widget widget) {
				String query = getQuery();
				Map<String, String> map = getStaticParameters();
				if ((query != null && query.length() > 0) || (map != null && map.size() > 0)) {
					searchServiceAsync.search(query, map, LIMIT, new AsyncCallback<List<Map<String,String>>>() {
					
						public void onSuccess(List<Map<String, String>> list) {
							printResults(list);
						}
					
						public void onFailure(Throwable throwable) {
							Window.alert(throwable.getMessage());				
						}
					});
				}
			}
		};
		searchButton.addClickListener(searchListener);
	}
	
	public void setMap(Map<String, Parameter> map) {
		this.map = map;
		createQueryTab(constructDynamicQueryPanel, true);
		createQueryTab(constructStaticQueryPanel, false);
		modelPanel = new TModelPanel(map);
	}

	private void createQueryTab(final VerticalPanel panel, final boolean dynamic) {
		QueryHorizontalPanel dynamicQueryPanel = dynamic ? new DynamicQueryPanel(map, searchListener) : new StaticQueryPanel(searchListener);
		panel.add(dynamicQueryPanel);
		widgetMap.put(dynamicQueryPanel.getLogicalOperatorListBox(), dynamicQueryPanel);
		
		dynamicQueryPanel.getLogicalOperatorListBox().addChangeListener(new ChangeListener() {
		
			public void onChange(Widget widget) {
				ListBox box = (ListBox) widget;
				if (box.getItemText(box.getSelectedIndex()).length() > 0) {
					if (panel.getWidget(panel.getWidgetCount() - 1).equals(widgetMap.get(box))) {
						QueryHorizontalPanel dynamicQueryPanel = dynamic ? new DynamicQueryPanel(map, searchListener) : new StaticQueryPanel(searchListener);
						panel.add(dynamicQueryPanel);
						
						widgetMap.put(dynamicQueryPanel.getLogicalOperatorListBox(), dynamicQueryPanel);
						dynamicQueryPanel.getLogicalOperatorListBox().addChangeListener(this);
					}
				} else {
					int i = panel.getWidgetCount() - 1;
					Widget w;
					do {
						w = panel.getWidget(i);
						i--;
						panel.remove(w);
					} while(!panel.getWidget(i).equals(widgetMap.get(box)));
				}
			}
		});
	}
	
	private String getQuery() {
		StringBuffer buffer = new StringBuffer();
		for (int i = 0; i < constructDynamicQueryPanel.getWidgetCount(); i++) {
			String query = ((DynamicQueryPanel) constructDynamicQueryPanel.getWidget(i)).getQuery();
			
			if (query != null) {
				buffer.append(query);
			}
		}
		
		return buffer.toString();
	}
	
	private Map<String, String> getStaticParameters() {
		Map<String, String> map = new HashMap<String, String>();
		for (int i = 0; i < constructStaticQueryPanel.getWidgetCount(); i++) {
			StaticQueryPanel panel = ((StaticQueryPanel) constructStaticQueryPanel.getWidget(i));
			
			if (panel.getParameter() != null && panel.getValue() != null && panel.getValue().trim().length() > 0) {
				map.put(panel.getParameter(), panel.getValue());
			}
		}
		
		return map;
	}
	
	private void printResults(List<Map<String, String>> list) {
		if (list == null) {
			grid.clear();
			grid.resize(0, 0);
			return;
		}
		
		List<String> nameList = new ArrayList<String>();
		for (Map<String, String> m : list) {
			for (String key : m.keySet()) {
				if (!nameList.contains(key)) {
					nameList.add(key);
				}
			}
		}
		Collections.sort(nameList);
		nameList.remove(SearchService.T_MODEL_KEY);
		grid.clear();
		grid.resize(list.size() + 1, nameList.size() + 1);
		grid.setWidth("100%");
		
		for (int i = 0; i < grid.getColumnCount(); i++) {
			grid.getColumnFormatter().setWidth(i, "10");
		}
		
		int row = 0;
		int column = 0;
		
		if (nameList.size() > 0) {
			grid.setText(row, column++, "TModelKey");
		} else {
			grid.setText(row, column++, "empty");
		}
		for (String name : nameList) {
			grid.setText(row, column++, name);	
		}
		row++;
		
		TModelClickListener clickListener = new TModelClickListener();
		
		for (Map<String, String> m : list) {
			column = 0;
			Hyperlink hyperlink = new Hyperlink(m.get(SearchService.T_MODEL_KEY), "tModelKey=" + m.get(SearchService.T_MODEL_KEY));
			hyperlink.addClickListener(clickListener);
			grid.setWidget(row, column++, hyperlink);
			for (String name : nameList) {
				if (m.get(name) != null) {
					grid.setText(row, column, m.get(name));
				} else {
					grid.setText(row, column, "");
				}
				column++;
			}
			row++;
		}
	}
	
	private class TModelClickListener implements ClickListener {

		public void onClick(Widget widget) {
			Hyperlink hyperlink = (Hyperlink) widget;
			final SearchServiceAsync searchServiceAsync = SearchService.Util.getInstance();
			final String tModelKey = hyperlink.getText();
			searchServiceAsync.getParameters(tModelKey, new AsyncCallback<Map<String,String>>() {
			
				public void onSuccess(Map<String, String> map) {
					modelPanel.setTModelParameters(tModelKey, map);
					RootPanel.get("panel").clear();
					RootPanel.get("panel").add(modelPanel);
				}
			
				public void onFailure(Throwable arg0) {
					Window.alert(arg0.getMessage());
				}
			});
		}
	}
	
}
